#!/usr/bin/env python
#
# validate.py
#
# Version : 0.7
# Date : 20080521
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

#
# validate.py - used to validate user input, run as part of skipolemonitor
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

"""validate.py - used to validate user input, run as part of skipolemonitor

It consists of a set of functions, used by other modules in skipolemonitor
which checks if parameters - usually from user input - are correct or not
""" 

import os
import sys
import ipv4_parse


# The directory where the script is kept
_SCRIPTDIRECTORY=os.path.abspath(os.path.dirname(sys.argv[0]))


# Error status (True if there is an error and string)
_ERROR_STATUS=False
_ERROR_STRING="No Error"


# These functions are used to set and read the error status and string and are
# used on program startup

def error_value():
    """Return _ERROR_STATUS and _ERROR_STRING"""
    global _ERROR_STATUS
    global _ERROR_STRING
    return _ERROR_STATUS, _ERROR_STRING

def set_error(error_status, error_string):
    """Sets the _ERROR_STATUS and _ERROR_STRING"""
    global _ERROR_STATUS
    global _ERROR_STRING
    _ERROR_STATUS = error_status
    _ERROR_STRING = error_string




# ------------- Utitily functions to check email address format

def check_mail_address(address):
    """Checks an email address, return 1 if ok, 0 if not"""
    #
    # Check address has an @ in it
    if address.count("@") != 1:
        return 0
    # Split the address into two halves
    SplitAddress=address.split('@')
    # Check both parts content
    if not check_part_address(SplitAddress[0]):
        return 0
    if not check_part_address(SplitAddress[1]):
        return 0
    # All tests pass, return 1
    return 1

def check_part_address(part):
    """Checks the part of the email address on either side of the @"""
    # Adress must only have numbers, letters, +, -, _ or . in it
    # Make sure there is some content
    if part == "":
        return 0
    # No leading or trailing .
    if part[0] == "." or part[-1] == ".":
        return 0
    # there cannot be two .. together
    if part.find("..") != -1:
        return 0
    # Create a string with all + replaced by letter a
    apart=part.replace("+", "a")
    # Create a string with all . replaced by letter a
    aapart=apart.replace(".", "a")
    # Create a string with all - replaced by letter a
    aaapart=aapart.replace("-", "a")
    # Create a string with all _ replaced by letter a
    aaaapart=aaapart.replace("_", "a")
    # This string must be alphanumeric only
    if not aaaapart.isalnum():
        return 0
    # All tests pass, return 1
    return 1

def check_mail_address_list(addresses):
    """Checks a list of ; separated email addresses, return 1 if ok, 0 if not"""
    # Does list have ; in it
    if addresses.count(";") == 0:
        # No it doesn't, so only one address, call check_mail_address
        return check_mail_address(addresses)
    # Break up the list
    address_list= addresses.split(";")
    # and for each of these, call check_mail_address
    for address in address_list:
        if check_mail_address(address) == 0:
            return 0
    # All tests pass, return 1
    return 1


# ----------------------- General validation functions

def is_text_integer(text, min, max):
    """Checks if the text is a string value of an integer, and if it is between
       min and max inclusive. Returns True if ok, False if not."""
    if not text.isdigit(): return False
    value=int(text)
    if value<min: return False
    if value>max: return False
    return True


def parse_csv_row(row):
    """Parses the list of four items taken from one row of a csv file"""
    # Return False if any error is found
    #
    # Check list has exactly four items
    if len(row) != 4: return False
    #
    # Check group name is 12 characters or less
    gname = row[0].strip()
    if len(gname)>12: return False
    #
    # Check group name is at least 1 character
    if len(gname)<1: return False
    #
    # Check a correct IP address is given
    ipaddress = row[1].strip()
    if ipv4_parse.parse(ipaddress, 32) == 0: return False
    #
    # Check host name is 12 characters or less
    hname = row[2].strip()
    if len(hname)>12: return False
    #
    # Check host name is at least 1 character
    if len(hname)<1: return False
    #
    # Check host description is 80 characters or less
    hdesc = row[3].strip()
    if len(hdesc)>80: return False
    #
    # So all seems ok
    return True

